﻿using System.Collections.Generic;
using System.Linq;
using Birkelund.QueryStrings.Internals;
using Birkelund.QueryStrings.Tokens;
using NUnit.Framework;

namespace Birkelund.QueryStrings.Test
{
    [TestFixture(typeof(HashChecksumCalculator))]
    [TestFixture(typeof(BasicChecksumCalculator))]
    public class ChecksumCalculatorTest<TCalculator> where TCalculator : IChecksumCalculator, new()
    {
        [TearDown]
        public void Cleanup()
        {
            QueryStringConfiguration.Instance.ChecksumCalculator = ChecksumCalculators.Basic;
        }
        
        [Test]
        public void CalculateCheckSum_DifferentCasingTest()
        {
            IEnumerable<TokenKeyValue> tokensBefore = ChecksumCalculatorTestHelper.CreateTokens("123", "abcø");
            IEnumerable<TokenKeyValue> tokensAfter = ChecksumCalculatorTestHelper.CreateTokens("123", "ABCØ");

            IChecksumCalculator calculator = new TCalculator();
            ChecksumCalculatorTestHelper.DoAssertion(calculator, tokensBefore, tokensAfter, false);
        }

        [Test]
        public void CalculateCheckSum_DifferentTextTest()
        {
            IEnumerable<TokenKeyValue> tokensBefore = ChecksumCalculatorTestHelper.CreateTokens("123", "abcø");
            IEnumerable<TokenKeyValue> tokensAfter = ChecksumCalculatorTestHelper.CreateTokens("123", "acbø");

            IChecksumCalculator calculator = new TCalculator();
            ChecksumCalculatorTestHelper.DoAssertion(calculator, tokensBefore, tokensAfter, false);
        }

        [Test]
        public void CalculateCheckSum_DifferentPositionTest()
        {
            IEnumerable<TokenKeyValue> tokensBefore = ChecksumCalculatorTestHelper.CreateTokens("123", "abcø");
            IEnumerable<TokenKeyValue> tokensAfter = tokensBefore.Reverse();

            IChecksumCalculator calculator = new TCalculator();
            ChecksumCalculatorTestHelper.DoAssertion(calculator, tokensBefore, tokensAfter, false);
        }

        [Test]
        public void CalculateCheckSum_NoValue()
        {
            IEnumerable<TokenKeyValue> tokensBefore = ChecksumCalculatorTestHelper.CreateTokens(string.Empty, string.Empty);
            IEnumerable<TokenKeyValue> tokensAfter = ChecksumCalculatorTestHelper.CreateTokens(string.Empty, string.Empty);

            IChecksumCalculator calculator = new TCalculator();
            ChecksumCalculatorTestHelper.DoAssertion(calculator, tokensBefore, tokensAfter, true);
        }

        [Test]
        public void CalculateCheckSum_ValidCheksum()
        {
            IEnumerable<TokenKeyValue> tokensBefore = ChecksumCalculatorTestHelper.CreateTokens("123", "abcø");
            IEnumerable<TokenKeyValue> tokensAfter = ChecksumCalculatorTestHelper.CreateTokens("123", "abcø");

            IChecksumCalculator calculator = new TCalculator();
            ChecksumCalculatorTestHelper.DoAssertion(calculator, tokensBefore, tokensAfter, true);
        }

        //test that the generated checksum is the same nomatter if the checksum is present or not (it must be ignored)
        [Test]
        public void CalculateCheckSum_ValidCheksumWithCheckSumKey()
        {
            IEnumerable<TokenKeyValue> tokensSimple = ChecksumCalculatorTestHelper.CreateTokens("123", "aBc_");
            
            IChecksumCalculator calculator = new TCalculator();
            string checksumSimple = calculator.CalculateCheckSum(tokensSimple);

            //---
            QueryStringConfiguration.Instance.ChecksumCalculator = calculator;
            var token1 = new StringToken("a");
            var token2 = new StringToken("b");
            
            IUriWriter writer = UriWriter.CreateEmptyFromUri("http://test.com/default.aspx");
            writer
                .SetToken(token1, "123")
                .SetToken(token2, "aBc_")
                .ApplyCheckSumControl = true;

            string generatedWithChecksumToken = CheckSumKeyToken.Instance.ReadValue(writer.GenerateQueryAsUri());
            //---

            Assert.AreEqual(generatedWithChecksumToken, checksumSimple);
        }
    }
}
